<template>
  <div ref="canvas"></div>
</template>

<script lang="ts" setup>
import * as THREE from "three";
import Stats from "three/examples/jsm/libs/stats.module";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { ref, onMounted } from "vue";

const canvas = ref();

const scene = new THREE.Scene();
const orthographicScene = new THREE.Scene();
// 渲染器
const renderer = new THREE.WebGLRenderer({ antialias : true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
// 相机
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 50);
camera.lookAt(0,0,0);
// orthographic 相机
const orthographicCamera = new THREE.OrthographicCamera(0, window.innerWidth, window.innerHeight, 0, -10, 10);
// 相机控件
const orbitControl = new OrbitControls(camera, renderer.domElement);
orbitControl.update();
// 性能统计
const stat = Stats();

// Sphere
const material = new THREE.MeshNormalMaterial();
const geom = new THREE.SphereGeometry(15, 20, 20);
const mesh = new THREE.Mesh(geom, material);

scene.add(mesh);
// gui
const controls = {
  size : 150,
  sprite : 0,
  transparent : true,
  opacity : 0.6,
  color : 0xffffff,
  redraw : () => {
    orthographicScene.children.forEach( (child) => {
      if (child instanceof THREE.Sprite) {
        orthographicScene.remove(child);
      }
    });
    createSprite(controls.size, controls.transparent, controls.opacity, controls.color, controls.sprite);
  },
};
const gui = new GUI();
// @ts-ignore
gui.add(controls, 'sprite', 0, 4).step(1).onChange(controls.redraw);
// @ts-ignore
gui.add(controls, 'size', 0, 120).onChange(controls.redraw);
// @ts-ignore
gui.add(controls, 'transparent').onChange(controls.redraw);
// @ts-ignore
gui.add(controls, 'opacity', 0, 1).onChange(controls.redraw);
// @ts-ignore
gui.addColor(controls, 'color').onChange(controls.redraw);

controls.redraw();

function createSprite(size, transparent, opacity, color, spriteNumber) {
  const texture = new THREE.TextureLoader().load(new URL("@/assets/textures/particles/sprite-sheet.png", import.meta.url).href);
  const spriteMaterial = new THREE.SpriteMaterial({
    opacity: opacity,
    color: color,
    transparent: transparent,
    map: texture,
  });

  spriteMaterial.map.offset = new THREE.Vector2(0.2 * spriteNumber, 0);
  spriteMaterial.map.repeat = new THREE.Vector2(1 / 5, 1);
  spriteMaterial.blending = THREE.AdditiveBlending;
  // make sure the object is always rendered at the front
  spriteMaterial.depthTest = false;

  const sprite = new THREE.Sprite(spriteMaterial);
  sprite.scale.set(size, size, size);
  sprite.position.set(100, 50, -10);
  // @ts-ignore
  sprite.velocityX = 5;

  orthographicScene.add(sprite);
}

let step = 0;
const render = () => {
  stat.update();

  camera.position.y = Math.sin(step += 0.01) * 20;

  orthographicScene.children.forEach(function (e) {
    if (e instanceof THREE.Sprite) {
      // move the sprite along the bottom
      // @ts-ignore
      e.position.x = e.position.x + e.velocityX;
      if (e.position.x > window.innerWidth) {
        // @ts-ignore
        e.velocityX = -5;
        controls.sprite += 1;
        e.material.map.offset.set(1 / 5 * (controls.sprite % 4), 0);
      }
      if (e.position.x < 0) {
        // @ts-ignore
        e.velocityX = 5;
      }
    }
  });

  // orbitControl.update();

  requestAnimationFrame(render);

  renderer.render(scene, camera);
  renderer.autoClear = false;
  renderer.render(orthographicScene, orthographicCamera);
};

onMounted(() => {
  canvas.value.appendChild(stat.domElement);
  canvas.value.appendChild(renderer.domElement);

  render();
});
</script>
